/*
 * app_cli.c
 *
 *  Created on: 2023年6月29日
 *      Author: HXF
 */

#include "app_cli.h"
#include "app_log.h"

static const char *status_to_string(int status)
{
  const char *string;

  switch (status) {
    case DS_STATUS_OK:
      string = "";
      break;
    case DS_STATUS_INVALID_PARAMETER:
      string = "The argument is not formatted correctly";
      break;
    case DS_STATUS_NOT_FOUND:
      string = "No command found";
      break;
    case DS_STATUS_HAS_OVERFLOWED:
      string = "Maximum number of arguments exceeded";
      break;
    case DS_STATUS_INVALID_TYPE:
      string = "Incorrect argument type";
      break;
    case DS_STATUS_INVALID_COUNT:
      string = "Incorrect number of arguments";
      break;
    case DS_STATUS_CLI_NO_DO:
      string = "";
      break;
    default:
      string = "Unknown error";
      break;
  }

  return string;
}

int DS_cli_handle_input(ds_cli_handle_t handle)
{
  if(!handle->input_buffer){
      DS_app_log_error("%s\r\n", status_to_string(DS_STATUS_INVALID_PARAMETER));
      return DS_STATUS_INVALID_PARAMETER;
  }
  if(handle->input_buffer[0] == '\0'){
      DS_app_log_error("%s\r\n", status_to_string(DS_STATUS_INVALID_PARAMETER));
      return DS_STATUS_INVALID_PARAMETER;
  }
  if(handle->input_size > DS_CLI_INPUT_BUFFER_SIZE){
      DS_app_log_error("%s\r\n", status_to_string(DS_STATUS_INVALID_PARAMETER));
      return DS_STATUS_INVALID_PARAMETER;
  }
  if(handle->input_size){
      if(handle->input_buffer[handle->input_size - 1] == '\n'){
          handle->input_buffer[handle->input_size - 1] = '\0';
          handle->input_size--;
      }
  }
  if(handle->input_size){
      if(handle->input_buffer[handle->input_size - 1] == '\r'){
          handle->input_buffer[handle->input_size - 1] = '\0';
          handle->input_size--;
      }
  }
  if(handle->input_size == 0){
      return DS_STATUS_CLI_NO_DO;
  }
  if(!handle->command_table){
      DS_app_log_error("%s\r\n", status_to_string(DS_STATUS_INVALID_PARAMETER));
      return DS_STATUS_INVALID_PARAMETER;
  }

  int status = DS_cli_command_execute(handle);
  if(status != DS_STATUS_OK){
      DS_app_log_info("%s\r\n", status_to_string(status));
  }
  return DS_STATUS_OK;
}

void DS_cli_input_clear(ds_cli_handle_t handle)
{
  memset(handle->input_buffer, '\0', DS_CLI_INPUT_BUFFER_SIZE);
  handle->input_size = 0;
  //handle->command_table = NULL;
}

int DS_cli_handle_work(ds_cli_handle_t handle)
{
  int status = DS_STATUS_OK;
  status = DS_cli_handle_input(handle);
  DS_cli_input_clear(handle);
  return status;
}

#if (CLI_TEST == 1)
//使用说明：
//1.用户定义ds_cli_t类型的实例，比如
//其中，input_buffer存放的是来自接收环形队列的完整数据
//input_size是数据长度
//command_table指向用户创建的命令列表
ds_cli_t ds_cli_example;
//2.用户定义ds_cli_handle_t，指向实例，用于传参
ds_cli_handle_t test_handle = &ds_cli_example;
//3.用户创建需要的ds_cli_command_entry_t命令列表，实现命令对应函数
//其中，name是命令名
//command里的function，是命令实现函数
//command里的arg_type_list，是命令的参数列表
void printf_hello(ds_cli_command_arg_t *arguments)
{
  (void)arguments;
  DS_app_log_debug("hello cli\r\n");
}

void printf_args(ds_cli_command_arg_t *arguments)
{
  int8_t i8 = ds_cli_get_argument_int8(arguments, 0);
  uint8_t ui8 = ds_cli_get_argument_uint8(arguments, 1);
  int16_t i16 = ds_cli_get_argument_int16(arguments, 2);
  uint16_t ui16 = ds_cli_get_argument_uint16(arguments, 3);
  int32_t i32 = ds_cli_get_argument_int32(arguments, 4);
  uint32_t ui32 = ds_cli_get_argument_uint32(arguments, 5);
  char *str = ds_cli_get_argument_string(arguments, 6);
  DS_app_log_debug("i8 %d\r\n",i8);
  DS_app_log_debug("ui8 %d\r\n",ui8);
  DS_app_log_debug("i16 %d\r\n",i16);
  DS_app_log_debug("ui16 %d\r\n",ui16);
  DS_app_log_debug("i32 %ld\r\n",i32);
  DS_app_log_debug("ui32 %ld\r\n",ui32);
  DS_app_log_debug("str %s\r\n",str);
}

static const ds_cli_command_info_t cli_cmd__printf_hello = \
    DS_CLI_COMMAND(printf_hello,
                 {DS_CLI_ARG_END, });

static const ds_cli_command_info_t cli_cmd__printf_args = \
    DS_CLI_COMMAND(printf_args,
                 {DS_CLI_ARG_INT8, DS_CLI_ARG_UINT8,
                     DS_CLI_ARG_INT16, DS_CLI_ARG_UINT16,
                     DS_CLI_ARG_INT32, DS_CLI_ARG_UINT32,
                     DS_CLI_ARG_STRING, DS_CLI_ARG_END, });

const ds_cli_command_entry_t ds_cli_default_command_table[] = {
    { "hello", &cli_cmd__printf_hello},
    { "testArgs", &cli_cmd__printf_args},
    { NULL, NULL},
};
//4。接收环形队列的数据遇到'\n'，数据都存入到input_buffer
//input_size赋值
//command_table指向命令列表
//DS_cli_test_init函数模拟了环形队列收到数据testArgs,-5,27,-369,417,-12345678,98765432,hello word
static void DS_cli_test_init(void)
{
#if(0)
  ds_cli_example.input_buffer[0] = 'h';
  ds_cli_example.input_buffer[1] = 'e';
  ds_cli_example.input_buffer[2] = 'l';
  ds_cli_example.input_buffer[3] = 'l';
  ds_cli_example.input_buffer[4] = 'o';
  ds_cli_example.input_size = 5;
#else
  ds_cli_example.input_size = strlen("testArgs,-5,27,-369,417,-12345678,98765432,hello world");
  memcpy(ds_cli_example.input_buffer,"testArgs,-5,27,-369,417,-12345678,98765432,hello world",ds_cli_example.input_size);
#endif
  ds_cli_example.command_table = ds_cli_default_command_table;
}
//5.用户调用DS_cli_handle_work函数
void DS_cli_test(void)
{
  DS_cli_test_init();
  int status = DS_cli_handle_work(test_handle);
  DS_app_log_debug("test status %x\r\n",status);
}
//6.例子里，相当于当用户串口输入testArgs,-5,27,-369,417,-12345678,98765432,hello world
//通过DS_cli_handle_work函数，
//提取参数，参数检查，执行函数printf_args
//输出
/*
i8 -5
ui8 27
i16 -369
ui16 417
i32 -12345678
u32 98765432
str hello world
*/
#endif
